#include "trans_file.h"
#include <my_header.h>
/* Usage:  */
int put_file_to_serv(tlv_msg_t cmd_msg,clientSession_t *user_session){
    //拿value里面的文件名
    char filename[4096] = {0};
    memcpy(filename,cmd_msg.value,cmd_msg.hdr.length);
    int fd = open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
    tlv_msg_t recv_pack;
    bzero(&recv_pack,sizeof(recv_pack));
    //1.接收文件长度
    int netfd = user_session->netfd;
    ssize_t recv_sret = tlv_recv(netfd,&recv_pack);
    if(recv_sret==1){
        close(fd);
        unlink(filename);
        printf("客户端下线\n");
        return 1;
    }
    off_t file_length;
    memcpy(&file_length,recv_pack.value,sizeof(file_length));
    //打印总的文件长度
    printf("%ld\n",file_length);
    //剩下的需要接收的字节长度
    off_t current_file_length = 0;

    while(current_file_length<file_length){
        bzero(&recv_pack,sizeof(recv_pack));
        //printf("开始上传文件\n");
        //每一轮接收的小火车
        recv_sret =  tlv_recv(netfd,&recv_pack);
        if(recv_sret==1){
            printf("传输过程中用户崩溃断线，清理下载资源\n");
            close(fd);
            unlink(filename);
            return 1;
        }
        //错误检查
        if(recv_pack.hdr.length!=4096){
            printf("%d\n",recv_pack.hdr.length);
        }

        ssize_t wriret = write(fd,recv_pack.value,recv_pack.hdr.length);
        if(wriret==-1){
            printf("文件写入失败\n");
        }
        //printf("下载成功一轮\n");
        current_file_length += recv_pack.hdr.length;
    }
    close(fd);
    printf("现已成功上传文件，断连时也保存文件\n");
    bzero(&recv_pack,sizeof(recv_pack));
    recv_sret = tlv_recv(netfd,&recv_pack);
    if(recv_sret==1){
        printf("客户端下线\n");
        return 1;
    }

    printf("%s,上传成功\n",recv_pack.value);
    tlv_msg_t response;
    bzero(&response,sizeof(response));
    char *reponse_msg = "上传成功";
    tlv_create(&response,DATA_END,strlen(reponse_msg),reponse_msg);
    ssize_t send_sret = tlv_send(netfd,&response);
    if(send_sret==1){
        printf("客户端下线\n");
        return 1;
    }
    return 0;
}

int get_file_from_serv(tlv_msg_t cmd_msg,clientSession_t *user_session){
    //接收客户端文件名
    char filename[4096]={0};
    memcpy(filename,cmd_msg.value,cmd_msg.hdr.length);
    //检查当前文件夹是否有对应文件
    int netfd = user_session->netfd;
    tlv_msg_t send_pack;
    bzero(&send_pack,sizeof(send_pack));
    if(access(filename,F_OK)==0){
        //本地文件存在
        send_pack.hdr.type = GETS_FILE_EXIST;
        int fd = open(filename,O_RDWR);
        struct stat file_info;
        bzero(&file_info,sizeof(file_info));
        fstat(fd,&file_info);
        off_t file_length = file_info.st_size;
        send_pack.hdr.length = sizeof(file_length);
        memcpy(send_pack.value,&file_length,sizeof(file_length));
        //将文件长度传给客户端
        ssize_t send_sret = tlv_send(netfd,&send_pack);
        if(send_sret==1){
            printf("客户端下线\n");
            return 1;
        }
        tlv_msg_t recv_pack;
        //获取客户端现有的文件长度
        bzero(&recv_pack,sizeof(recv_pack));
        ssize_t recv_sret = tlv_recv(netfd,&recv_pack);
        if(recv_sret==1){
            printf("客户端下线\n");
            return 1;
        }
        //获取客户端现有的文件长度
        off_t current_file_length;
        memcpy(&current_file_length,recv_pack.value,recv_pack.hdr.length);
        //剩下的需要继续传输的文件长度
        off_t rest_file_length = file_length-current_file_length;
        off_t limit_file_length = 100000000;
        if(rest_file_length>limit_file_length){
            //剩余文件大小大于100mb使用mmap进行文件传输
            if (ftruncate(fd, file_length) == -1) {
                perror("ftruncate failed");
            }
            off_t offset_length = (current_file_length/4096)*4096;
            off_t rest_mapping_length = file_length-offset_length;
            char *p = (char *)mmap(NULL,rest_mapping_length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,offset_length);
            //本次累计发送的字节数量
            off_t send_length_thisturn = current_file_length - offset_length;
            //每次发出的数据包长度
            int send_data_once;
            //专门声明个用于数据发送的包
            tlv_msg_t send_data_pack;
            while(current_file_length<file_length){

                bzero(&send_data_pack,sizeof(send_data_pack));
                send_data_once = ((file_length-current_file_length)<4096)?(file_length-current_file_length):4096;
                send_data_pack.hdr.type = DATA_CHUNK;
                send_data_pack.hdr.length = send_data_once;
                memcpy(send_data_pack.value, p+send_length_thisturn, send_data_once);
                //错误检查
                if(send_data_once!=4096){
                    printf("%d\n",send_data_once);
                }
                tlv_send(netfd, &send_data_pack);
                if(send_sret==1){
                    close(fd);
                    printf("大文件下载过程中，客户端下线\n");
                    return 1;
                }

                send_length_thisturn += send_data_once;
                current_file_length += send_data_once;
            }
            close(fd);
            munmap(p,rest_mapping_length);
            //文件传输结束
            bzero(&send_pack,sizeof(send_pack));
            send_data_pack.hdr.type = DATA_END;
            char *trans_finish="大内容传输完成";
            printf("他要的东西我已经传完啦\n");
            send_data_pack.hdr.length = strlen(trans_finish);
            memcpy(send_data_pack.value,trans_finish,send_data_pack.hdr.length);
            send_sret = tlv_send(netfd,&send_data_pack);
            if(send_sret==1){
                printf("下载传输结束，客户端下线\n");
                return 1;
            }
            printf("%s\n",trans_finish);

        }
        else{
            //剩余文件大小小于100mb使用read函数进行进行文件传输
            char buf[4096];
            bzero(buf,sizeof(buf));
            tlv_msg_t send_data_pack;
            bzero(&send_data_pack,sizeof(send_data_pack));
            off_t offset_result = lseek(fd, current_file_length, SEEK_SET);
            if (offset_result == (off_t)-1) {
                perror("lseek failed");
                close(fd);
                return 2;
            }
            int send_data_once;
            //int i = 0;
            while(current_file_length<file_length){
                //printf("i = %d\n",i++);
                bzero(&send_data_pack,sizeof(send_data_pack));
                send_data_pack.hdr.type = DATA_CHUNK;
                bzero(buf,sizeof(buf));
                send_data_once = read(fd,buf,sizeof(buf));

                //printf("%d\n",send_data_once);
                if(send_data_once==0){
                    printf("通过read的文件传输结束\n");
                    break;
                }
                //错误打印
                if(send_data_once!=4096){
                    printf("%d\n",send_data_once);
                }
                send_data_pack.hdr.length = send_data_once;
                memcpy(send_data_pack.value,buf,send_data_once);
                ssize_t send_sret = tlv_send(netfd,&send_data_pack);
                //客户端断连接
                if(send_sret==1){
                    printf("小文件下载过程中，客户端下线\n");
                    close(fd);
                    return 1;
                }
                current_file_length += send_data_once;
            }
            bzero(&send_data_pack,sizeof(send_data_pack));
            send_data_pack.hdr.type = DATA_END;
            char *trans_finish="小内容传输完成";
            printf("他要的东西我已经传完啦\n");
            send_data_pack.hdr.length = strlen(trans_finish);
            memcpy(send_data_pack.value,trans_finish,send_data_pack.hdr.length);
            send_sret = tlv_send(netfd,&send_data_pack);
            if(send_sret==1){
                printf("下载传输结束，客户端下线\n");
                return 1;
            }
            printf("%s\n",trans_finish);
        }
    }else{
        //本地文件不存在
        send_pack.hdr.type = GETS_FILE_NOEXIST;
        char *response = "文件不存在，下载失败";
        send_pack.hdr.length = strlen(response);
        memcpy(send_pack.value,response,strlen(response));
        ssize_t send_sret = tlv_send(netfd,&send_pack);
        if(send_sret==1){
            printf("客户端下线\n");
            return 1;
        }
    }
    return 0;
}
